package com.szgr.baoyin.video;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;


import com.szgr.baoyin.R;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * 视频在加载信息，即一开始loading的过程，设置seekbar为不可拖动的，或者不处理，在prepare完成后设置监听 点击屏幕显示controller
 * 2秒后消失，如果点击显示后，这个时候一直拖动进度条，应该用户无任何操作后2秒消失 处理 onPause、onStop、onDestroy
 * mPlayPosition没有记录参考系统
 */
public class FullScreenVideoActivity extends Activity implements View.OnClickListener,
        MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener,
        MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
        MediaPlayer.OnBufferingUpdateListener, MediaPlayerControl {

    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private SeekBar mSeekBar;
    private ProgressBar mProgressbar;
    /**
     * controller面板
     */
    private View mController;
    private View loadView;
    private TextView mBufferPercent;

    private int videoLen;

    private TextView mCurrTime;
    private TextView mSumTime;

    // private ImageButton mPauseBtn;
    private Button mPauseBtn;
    /**
     * 视频信息加载失败，重试
     */
    private Button mRetryBtn;

    /**
     * 播放视频
     */
    private MediaPlayer mPlayer;

    /**
     * 记录当前播放的位置
     */
    private int mPlayPosition = -1;

    /**
     * seekBar是否自动拖动
     */
    private boolean seekBarAutoFlag = false;

    /**
     * 屏幕的宽度和高度
     */
    private int screenWidth, screenHeight;
    private TextView mTitle;
    /**
     * 改变尺寸
     */
    private Button btnSize;

    private String path;

    /**
     * 当前缓存进度
     */
    private int mCurrentBufferPercentage;

    /**
     * mediaController是否显示
     */
    private boolean mShowing;
    private static final int sDefaultTimeout = 3000;
    private static final int FADE_OUT = 1;
    private static final int SHOW_PROGRESS = 2;

    /**
     * 是否是错误状态
     */
    private boolean isError = false;

    /**
     * 记录当前视频状态 0:暂停 1:播放 2:重试（加载视频失败，重试）
     */
    // private int currState = -1;
    public boolean isError() {
        return isError;
    }

    @Override
    public void start() {
        if (mPlayer != null && mPlayer.isPlaying()) {
            mPlayer.start();
        }
    }

    @Override
    public void pause() {
        if (mPlayer != null && mPlayer.isPlaying()) {
            mPlayer.pause();
        }
    }

    @Override
    public int getDuration() {
        return mPlayer.getDuration();
    }

    @Override
    public int getCurrentPosition() {
        return mPlayer.getCurrentPosition();
    }

    @Override
    public void seekTo(int msec) {
        mPlayer.seekTo(msec);
    }

    @Override
    public boolean isPlaying() { // 如果视频无法播放，mPlayer.isPlaying()的返回值应该是false
        // return isInPlaybackState() && mMediaPlayer.isPlaying();
        // fixme return isError() && mMediaPlayer.isPlaying();
        return mPlayer.isPlaying();
    }

    @Override
    public int getBufferPercentage() {
        if (mPlayer != null) {
            return mCurrentBufferPercentage;
        }
        return 0;
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            Log.i("fcy", "------------- handler.msg.what=" + msg.what);
            int pos;
            switch (msg.what) {
                case FADE_OUT: // 隐藏
                    hide();
                    break;
                case SHOW_PROGRESS: // 更新进度条
                    pos = setProgress(); // 当前播放位置（毫秒数）
                    if (mShowing && mPlayer.isPlaying()) { // 在handleMessage中再次发送消息（延迟发送，形成每隔x发送一次）
                        msg = obtainMessage(SHOW_PROGRESS);
                        // fixme 为什么不是1000
                        sendMessageDelayed(msg, 1000 - (pos % 1000));
                    }
                    break;
            }
        }
    };

    /**
     * 设置播放进度条、缓冲进度、视频总时长，当前播放位置
     *
     * @return 当前播放的位置（milliseconds）
     */
    private int setProgress() {
        int position = mPlayer.getCurrentPosition();
        int duration = mPlayer.getDuration();
        if (mSeekBar != null) {
            if (duration > 0) {
                // use long to avoid overflow
                long pos = 1000L * position / duration;
                mSeekBar.setProgress((int) pos);
            }
            int percent = getBufferPercentage();
            mSeekBar.setSecondaryProgress(percent * 10);
        }

        if (mSumTime != null) // fixme 每次都设置好么？放到prepare完成后，设置一下就好了
            mSumTime.setText(getShowTime(duration));
        if (mCurrTime != null)
            mCurrTime.setText(getShowTime(position));

        return position;
    }

    /**
     * Remove the controller from the screen.
     */
    public void hide() {
        // if (mAnchor == null)
        // return;

        if (mShowing) {
            try { // 隐藏的时候，将消息移除，不再处理该消息（进度条不再走，只有显示的时候才处理进度条）
                mHandler.removeMessages(SHOW_PROGRESS);
                // 隐藏controller
                // mWindowManager.removeView(mDecor);

                if (mController != null) {
                    mController.setVisibility(View.GONE);
                }
            } catch (IllegalArgumentException ex) {
                Log.w("MediaController", "already removed");
            }
            mShowing = false;
        }
    }

    /**
     * Show the controller on screen. It will go away automatically after 3
     * seconds of inactivity.
     */
    public void show() {
        show(sDefaultTimeout);
    }

    /**
     * TODO Show the controller on screen. It will go away automatically after
     * 'timeout' milliseconds of inactivity.
     *
     * @param timeout The timeout in milliseconds. Use 0 to show the controller
     *                until hide() is called.
     */
    public void show(int timeout) {
        if (!mShowing) {
            setProgress();
            if (mPauseBtn != null) {
                mPauseBtn.requestFocus();
            }
            // 显示 MediaController
            // mWindowManager.addView(mDecor, mDecorLayoutParams);
            mController.setVisibility(View.VISIBLE);
            mShowing = true;
        }
        updatePausePlay(0);

        // cause the progress bar to be updated even if mShowing
        // was already true. This happens, for example, if we're
        // paused with the progress bar showing the user hits play.
        mHandler.sendEmptyMessage(SHOW_PROGRESS);
        Message msg = mHandler.obtainMessage(FADE_OUT);

        // fixme 系统方法：但是如果调用了show(3000)3s内又调用show(0),那么同样会被隐藏
        // if (timeout != 0)
        // { // 如果是0，那么将消失的msg移除，且不发送, 即会一直显示
        // mHandler.removeMessages(FADE_OUT);
        // mHandler.sendMessageDelayed(msg, timeout);
        // }

        if (timeout != 0) { // 如果是0，那么将消失的msg移除，且不发送, 即会一直显示
            mHandler.removeMessages(FADE_OUT);
            mHandler.sendMessageDelayed(msg, timeout);
        } else { // 修改系统方法
//			Message message = mHandler.obtainMessage(FADE_OUT);
//			if (message != null)
//			{
            mHandler.removeMessages(FADE_OUT);
//			}
        }

    }

    public boolean isShowing() {
        return mShowing;
    }

    private void toggleMediaControlsVisibility() {
        if (isShowing()) {
            hide();
        } else {
            show();
        }
    }

    /**
     * 更新暂停图标（暂停、播放、重试）
     */
    private void updatePausePlay(int state) {
        if (mPlayer.isPlaying()) {
            // mPauseBtn.setImageResource(com.android.internal.R.drawable.ic_media_pause);
            mPauseBtn.setText("暂停");
        } else {
            // mPauseBtn.setImageResource(com.android.internal.R.drawable.ic_media_play);
            mPauseBtn.setText("播放");
        }
    }

    private void initIntent(Bundle bundle) { // 传递 视频播放url
        path = "http://img1.peiyinxiu.com/2014121211339c64b7fb09742e2c.mp4";
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.main);

        initIntent(null);
        // 获取屏幕的宽度和高度
        DisplayMetrics displayMetrics = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        screenWidth = displayMetrics.widthPixels;
        screenHeight = displayMetrics.heightPixels;
        init();
    }

    private void init() {
        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        mSurfaceView.setOnClickListener(this);
        mController = findViewById(R.id.ll_controller);
        // mController.setOnClickListener(this);

        mTitle = (TextView) findViewById(R.id.tv_title);
        btnSize = (Button) findViewById(R.id.btn_change_size);

        mSeekBar = (SeekBar) findViewById(R.id.seekBar);
        mSeekBar.setMax(1000);
        mCurrTime = (TextView) findViewById(R.id.tv_curr_time);
        mSumTime = (TextView) findViewById(R.id.tv_sum_time);

        findViewById(R.id.btn_back).setOnClickListener(this);
        // 暂停/播放
        // mPauseBtn = (ImageButton) findViewById(R.id.btn_pause);
        mPauseBtn = (Button) findViewById(R.id.btn_pause);
        mPauseBtn.setOnClickListener(this);

        loadView = findViewById(R.id.ll_buffer);
        mProgressbar = (ProgressBar) findViewById(R.id.progressBar);
        showLoadingProgressbar(true);
        mBufferPercent = (TextView) findViewById(R.id.tv_buffer_percent);

        mRetryBtn = (Button) findViewById(R.id.btn_retry);
        mRetryBtn.setOnClickListener(this);

        mSurfaceView.getHolder().addCallback(mSHCallback);
        mSurfaceView.getHolder().setType(
                SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mSurfaceView.setFocusable(true);
        mSurfaceView.setFocusableInTouchMode(true);
        mSurfaceView.requestFocus();
    }

    SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
        public void surfaceChanged(SurfaceHolder holder, int format, int w,
                                   int h) {
            // if (mSeekWhenPrepared != 0)
            // {
            // seekTo(mSeekWhenPrepared);
            // }
            if (mPlayPosition != 0) {
                seekTo(mPlayPosition);
            }

            start();
        }

        public void surfaceCreated(SurfaceHolder holder) {
            mSurfaceHolder = holder;
            openVideo();
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // after we return from this we can't use the surface any more
            mSurfaceHolder = null;
            hide();
            release();
        }
    };

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            // case R.id.ll_controller:
            case R.id.surfaceView:
                toggleMediaControlsVisibility();
                break;
            case R.id.btn_back:
                finish();
                break;
            case R.id.btn_pause: // 暂停/播放
                doPauseResume();
                // show();
                break;
            case R.id.btn_retry: // 获取视频信息失败，重试
                Toast.makeText(this, "加载视频错误！", Toast.LENGTH_LONG).show();
                break;
            case R.id.btn_change_size:
                 changeVideoSize();
                break;
        }
    }

    private void doPauseResume() {
        show();
        if (mPlayer.isPlaying()) {
            mPlayer.pause();
        } else {
            mPlayer.start();
        }
        updatePausePlay(0);
    }

    /**
     * 改变视频的显示大小，全屏，窗口，内容
     */
     public void changeVideoSize()
     {
     // 改变视频大小
     String videoSizeString = btnSize.getText().toString();
     // 获取视频的宽度和高度
     int width = mPlayer.getVideoWidth();
     int height = mPlayer.getVideoHeight();
     // 如果按钮文字为窗口则设置为窗口模式
     if ("窗口".equals(videoSizeString))
     {
     /*
     * 如果为全屏模式则改为适应内容的，前提是视频宽高小于屏幕宽高，如果大于宽高 我们要做缩放
     * 如果视频的宽高度有一方不满足我们就要进行缩放. 如果视频的大小都满足就直接设置并居中显示。
     */
     if (width > screenWidth || height > screenHeight)
     {
     // 计算出宽高的倍数
     float vWidth = (float) width / (float) screenWidth;
     float vHeight = (float) height / (float) screenHeight;
     // 获取最大的倍数值，按大数值进行缩放
     float max = Math.max(vWidth, vHeight);
     // 计算出缩放大小,取接近的正值
     width = (int) Math.ceil((float) width / max);
     height = (int) Math.ceil((float) height / max);
     }
     // 设置SurfaceView的大小并居中显示
     RelativeLayout.LayoutParams layoutParams = new
     RelativeLayout.LayoutParams(
     width, height);
     layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
     mSurfaceView.setLayoutParams(layoutParams);
         btnSize.setText("全屏");
     }
     else if ("全屏".equals(videoSizeString))
     {
     // 设置全屏
     // 设置SurfaceView的大小并居中显示
     RelativeLayout.LayoutParams layoutParams = new
     RelativeLayout.LayoutParams(
     screenWidth, screenHeight);
     layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
         mSurfaceView.setLayoutParams(layoutParams);
         btnSize.setText("窗口");
     }
     }

	/*
     * release the media player in any state
	 */
    private void release() {
        if (mPlayer != null) {
            mPlayer.reset();
            mPlayer.release();
            mPlayer = null;
        }
    }

    /**
     * 播放视频
     */
    public void openVideo() {
        release(); // release(false)
        // 初始化MediaPlayer
        mPlayer = new MediaPlayer();
        // 重置mediaPalyer,建议在初始化mediaplay立即调用。
        // mPlayer.reset();
        // 设置声音效果
        // mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        // 设置播放完成监听
        mPlayer.setOnCompletionListener(this);
        mPlayer.setOnInfoListener(this);
        // 设置媒体加载完成以后回调函数，可以播放了
        mPlayer.setOnPreparedListener(this);
        // 错误监听回调函数
        mPlayer.setOnErrorListener(this);
        // 设置缓存变化监听
        mPlayer.setOnBufferingUpdateListener(this);
        mCurrentBufferPercentage = 0;
        // 传递url
        if (TextUtils.isEmpty(path)) {
            Toast.makeText(this, "加载视频错误！", Toast.LENGTH_LONG).show();
            return;
        }
        // fixme 这里也可能异常，建议放到try里，cath exception
        Uri uri = Uri.parse(path);
        try {
            mPlayer.setDataSource(this, uri);
            // 设置异步加载视频，包括两种方式 prepare()同步，prepareAsync()异步
            // mPlayer.prepare();

            mPlayer.setDisplay(mSurfaceHolder);
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mPlayer.setScreenOnWhilePlaying(true);
            mPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "加载视频错误！", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 播放完成的监听
     *
     * @param mp
     */
    @Override
    public void onCompletion(MediaPlayer mp) {
        hide();

        Log.i("fcy", "------------- onCompletion=播放结束");
        // // TODO 播放完成，是否提示再看一遍
        // // 设置seeKbar跳转到最后位置
        // mSeekBar.setProgress(videoLen);
        // // 设置播放标记为false
        // seekBarAutoFlag = false;
    }

    /**
     * 更新loading状态
     *
     * @param isLoading
     */
    public void updateLoadState(boolean isLoading) {
        if (isLoading) {// 正在加载
            show(0);
            showLoadingProgressbar(true);
        } else {
            hide();
            showLoadingProgressbar(false);
        }
    }

    /**
     * 视频卡顿时加载的监听，用于在卡顿的时候显示 loading
     *
     * @param mp
     * @param what
     * @param extra
     * @return
     */
    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        Log.i("fcy", "------------- onInfo.what=" + what);
        switch (what) {
            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
                updateLoadState(false);
                return true;
            }
            case MediaPlayer.MEDIA_INFO_BUFFERING_START: { // 卡顿的时候，让controller一直显示，知道开始播放才消失
                updateLoadState(true);
                return true;
            }
            case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
                updateLoadState(false);
                return true;
            }
        }
        return false;
    }

    /**
     * 转换播放时间
     *
     * @param milliseconds 传入毫秒值
     * @return 返回 hh:mm:ss或mm:ss格式的数据
     */
    @SuppressLint("SimpleDateFormat")
    public String getShowTime(long milliseconds) {
        // 获取日历函数
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(milliseconds);
        SimpleDateFormat dateFormat = null;
        // 判断是否大于60分钟，如果大于就显示小时。设置日期格式
        if (milliseconds / 60000 > 60) {
            dateFormat = new SimpleDateFormat("hh:mm:ss");
        } else {
            dateFormat = new SimpleDateFormat("mm:ss");
        }
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 是否要显示
     *
     * @param isShow
     */
    public void showLoadingProgressbar(boolean isShow) {
        if (mProgressbar == null)
            return;

        if (isShow) { // 需要显示
            mProgressbar.setVisibility(View.VISIBLE);
            mPauseBtn.setVisibility(View.GONE);
        } else {
            mProgressbar.setVisibility(View.GONE);
            mPauseBtn.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 视频信息加载完毕回调
     *
     * @param mp
     */
    @Override
    public void onPrepared(MediaPlayer mp) {
        // 当视频加载完毕以后，为什么会立刻隐藏加载进度条，哪里掉了hide（如果想加载完毕后，等2s再隐藏，那么）
        // 为什么使用下面两行，依然会立刻隐藏，如果不调用show只调用第二行，那么就不会hide了
        // show(5000);
        showLoadingProgressbar(false);
//		updateLoadState(false); // 包含了hide方法

        // 判断是否有保存的播放位置,防止屏幕旋转时，界面被重新构建，播放位置丢失。
        if (mPlayPosition > 0) {
            mPlayer.seekTo(mPlayPosition);
        }

//		if (mSumTime != null)
//			mSumTime.setText(getShowTime(mPlayer.getDuration()));

        // 设置拖动监听事件
        mSeekBar.setOnSeekBarChangeListener(new SeekBarChangeListener());
        // 视频大小
        btnSize.setOnClickListener(this);
        // TODO 播放视频
        mPlayer.start();
        // 设置显示到屏幕
        // mPlayer.setDisplay(mSurfaceHolder);
//		show(5000);
        show();
        // TODO 设置surfaceView保持在屏幕上
        // mPlayer.setScreenOnWhilePlaying(true);
        // mSurfaceHolder.setKeepScreenOn(true);

    }

    /**
     * 播放失败的回调
     *
     * @param mp
     * @param what
     * @param extra
     * @return
     */
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) { // what = -38
        Log.i("fcy", "-------------播放失败：what=" + what + ",extra=" + extra);
        switch (what) {
            case MediaPlayer.MEDIA_ERROR_UNKNOWN:
                Toast.makeText(this, "MEDIA_ERROR_UNKNOWN", Toast.LENGTH_SHORT)
                        .show();
                break;
            case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
                Toast.makeText(this, "MEDIA_ERROR_SERVER_DIED",
                        Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }

        switch (extra) {
            case MediaPlayer.MEDIA_ERROR_IO:
                Toast.makeText(this, "MEDIA_ERROR_IO", Toast.LENGTH_SHORT)
                        .show();
                break;
            case MediaPlayer.MEDIA_ERROR_MALFORMED:
                Toast.makeText(this, "MEDIA_ERROR_MALFORMED",
                        Toast.LENGTH_SHORT).show();
                break;
            case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
                Toast.makeText(this,
                        "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK",
                        Toast.LENGTH_SHORT).show();
                break;
            case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
                Toast.makeText(this, "MEDIA_ERROR_TIMED_OUT",
                        Toast.LENGTH_SHORT).show();
                break;
            case MediaPlayer.MEDIA_ERROR_UNSUPPORTED: // 不支持
                Toast.makeText(this, "MEDIA_ERROR_UNSUPPORTED",
                        Toast.LENGTH_SHORT).show();
                break;
        }
        return false;
    }

    /**
     * 播放缓冲的回调
     *
     * @param mp
     * @param percent
     */
    @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {
        mCurrentBufferPercentage = percent;
    }

    /**
     * 进度条 状态改变监听
     */
    private class SeekBarChangeListener implements
            SeekBar.OnSeekBarChangeListener {

        public void onProgressChanged(SeekBar seekBar, int progress,
                                      boolean fromUser) {
            if (!fromUser) {
                return;
            }

            long duration = mPlayer.getDuration();
            long newPosition = (duration * progress) / 1000L;
            mPlayer.seekTo((int) newPosition);
            if (mCurrTime != null)
                mCurrTime.setText(getShowTime((int) newPosition));

            // 无任何操作后2s后消失，需要调用show(),否则按上次调用show()算后2s消失
            show();
        }

        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        public void onStopTrackingTouch(SeekBar seekBar) {
        }

    }

}
